
import os
import pandas as pd
import numpy as np
from data_deal.merger import fileTodf
from data_deal.merger import long_term_ecg_deal

# 加入polar的HR和rr的stage数据
def stage_add_polar(stages,rrdata_df):
    

    rrdata_df['timestamp'] = rrdata_df['timestamp'].astype('int64')
    import ast
    rrdata_df['rr'] = rrdata_df['rr'].apply(ast.literal_eval)
    stages['polar_hr']=None
    stages['polar_rr']=None

    for index, stage in stages.iterrows():
        
        
        start_time=stage['start_stamp']
        end_time=stage['end_stamp']
        #设置规则可以在这里进行
        stage_rrdata = rrdata_df[(rrdata_df['timestamp'] > start_time) & (rrdata_df['timestamp'] < end_time)]
        hr_list = stage_rrdata['HR'].astype(int).tolist()
        rr_list = [int(item) for sublist in stage_rrdata['rr'] for item in sublist if item and item != '']
    
        stages.at[index, 'polar_hr'] = hr_list
        stages.at[index, 'polar_rr'] = rr_list

    # print(stages)
    return stages
# 设置获取阶段中的哪部分时间段，
def stage_add_polar_rule(stages,rrdata_df):
    

    rrdata_df['timestamp'] = rrdata_df['timestamp'].astype('int64')
    import ast
    rrdata_df['rr'] = rrdata_df['rr'].apply(ast.literal_eval)
    stages['polar_hr']=None
    stages['polar_rr']=None

    for index, stage in stages.iterrows():
        
        
        start_time=stage['start_stamp']
        end_time=stage['end_stamp']
        #设置规则可以在这里进行
        #将整个时间段比作100%,开始时间可以设置为0%，结束时间设置为100%
        startstep=0
        endstep=1
        timestage=end_time-start_time
        start_time=start_time+startstep*timestage
        end_time=end_time-(1-endstep)*timestage


        stage_rrdata = rrdata_df[(rrdata_df['timestamp'] > start_time) & (rrdata_df['timestamp'] < end_time)]


        hr_list = stage_rrdata['HR'].astype(int).tolist()
        rr_list = [int(item) for sublist in stage_rrdata['rr'] for item in sublist if item and item != '']
    
        stages.at[index, 'polar_hr'] = hr_list
        stages.at[index, 'polar_rr'] = rr_list

    # print(stages)
    return stages
#得到处理后的stage数据，形成室内数据的stage
def stage_get(number,record,ecg_df):
    '''
    :param number: 1000000000000000000000000000
    :param record: 读取的记录表
    :ecg_df: ecg数据
    :return:
    '''
    record.replace({pd.NA: None, pd.NaT: None, np.nan: None}, inplace=True)
    filtered_record = record[record['number'] == number]
    rest=filtered_record['Resting'].values
    sex=filtered_record['sex'].values
    # print('性别',sex)
    if sex == 0:
        speed=[4,5.2,6.4,7.6,8.8,10,11.2,12.4,13.6,14.8,16,17.2,18.4,19.6,20.8]
    elif sex==1:
        speed=[5,6.2,7.4,8.6,9.8,11,12.2,13.4,14.6,15.8,17,18.2,19.4,20.6,21.8]
    
    columns_run = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12','13','14','15']
    selected_columns = filtered_record.loc[:, columns_run]
    # print('select',selected_columns)
    la = selected_columns.values.flatten().tolist()
    la =  [x for x in la if x is not None]
    # print('la',la)
    
   
    stage=stage_divide(number,ecg_df)
    
    stage['la'] = None
    # stage['speed km/h']=None
    stage.loc[stage['state'] == 'rest', 'la'] = rest
    running_rows = stage[stage['state'] == 'running']
    print('血乳酸',la)
    print(running_rows)
    if len(la) != len(running_rows):
        raise ValueError(f"la 的长度与 state='running' 的行数不匹配,stage的长度为{len(stage)}，la的长度为{len(la)}")

    # 增加一列 'la'，初始值为 None 或者其他默认值

    # 将 state 字段等于 'running' 的行的 'la' 列赋值为 some_list
    stage.loc[stage['state'] == 'running', 'la'] = la
    stage.loc[stage['state'] == 'running', 'speed'] = speed[0:len(la)]
    # 查看结果
    
    return stage



def stage_divide_info(number,ecg_df):
    'stage psychology_RPE physiology_RPE'
   
    stage_info=[]
    df=ecg_df
    df.iloc[:, 0] = df.iloc[:, 0].apply(lambda x: int(str(x)[:13]))
  
    df['ecg_time'] = pd.to_datetime(df.iloc[:, 0], unit='ms', utc=True).dt.tz_convert('Asia/Shanghai')
    df['ecg_time'] = df['ecg_time'].dt.strftime('%Y-%m-%d %H:%M:%S.%f').str[:-3]
    stage_filtered_data =df[(df['stage'].ne(df['stage'].shift())) & (df['stage'] != '-')]['stage'].tolist()
    psychology_RPE_filtered_data = df[(df['psychology_RPE'].ne(df['psychology_RPE'].shift())) & (df['psychology_RPE'] != '-')]['psychology_RPE'].tolist()
    physiology_RPE_filtered_data = df[(df['physiology_RPE'].ne(df['physiology_RPE'].shift())) & (df['physiology_RPE'] != '-')]['physiology_RPE'].tolist()
    # print(f'stage{stage_filtered_data}长度{len(stage_filtered_data)}')
    # print(f'psychology_RPE{psychology_RPE_filtered_data}长度{len(psychology_RPE_filtered_data)}')
    # print(f'physiology_RPE{physiology_RPE_filtered_data}长度{len(physiology_RPE_filtered_data)}')
    
    if len(stage_filtered_data)==len(psychology_RPE_filtered_data)==len(physiology_RPE_filtered_data):
        # print('数据没有问题')
        stage_info.append([len(stage_filtered_data),len(psychology_RPE_filtered_data),len(physiology_RPE_filtered_data),'没问题'])
    else:
        # print('数据有问题')
        stage_info.append([len(stage_filtered_data),len(psychology_RPE_filtered_data),len(physiology_RPE_filtered_data),'有问题'])
    stage_info.append(stage_filtered_data)
    stage_info.append(psychology_RPE_filtered_data)
    stage_info.append(physiology_RPE_filtered_data)
    print(stage_info)
    

    return stage_info
    
    
    
    
    
    

def rpe_get(file):
    print('开始读取文件')
    print(file)
    # ecg = long_term_ecg_deal(file)
    ecg=pd.read_csv(file)
    print(ecg)

    # 获取每列中第一个非'-'的值，如果没有有效值则返回空
    psychology_RPE = ecg[ecg['psychology_RPE'] != '-']['psychology_RPE'].unique().tolist()
    physiology_RPE = ecg[ecg['physiology_RPE'] != '-']['physiology_RPE'].unique().tolist()
    now_RPE = ecg[ecg['now_RPE'] != '-']['now_RPE'].unique().tolist()
    train_RPE = ecg[ecg['train_RPE'] != '-']['train_RPE'].unique().tolist()
    # print(file)
    # print(psychology_RPE,physiology_RPE,now_RPE,train_RPE)
    # 返回所有列表组成的一个总列表
    return [psychology_RPE, physiology_RPE, now_RPE, train_RPE]
    

#将ecg中的阶段和rpe提取，得到每个阶段开始和结束时间
def stage_divide(number,ecg_df):
    pd.set_option('display.max_columns', None)
    # 设置显示宽度，防止自动换行
    pd.set_option('display.width', 1000)
    '''
    # 跑步阶段划分,并实现每个阶段的标注，方便之后处理
    #输入合并后完整的ecg，输出 一个df 包括每个阶段的stage，开始时间，结束时间，心理rpe，生理rpe
    #可在此步做检查判断每个阶段的时间差和阶段与阶段之间的时间差，从而得到检查该数据是否有问题
    #循环该df也可以得到对应阶段的df，或函数内部也有 groupe  可作为输出
    :param ecg_df:
    :return: df:每个阶段的一个开始结束阶段等
    example:
        stage               start_time                 end_time    start_stamp      end_stamp psychology_RPE physiology_RPE      name
0       1  2024-07-26 09:51:32.275  2024-07-26 09:59:45.463  1721958692275  1721959185463              0              0      rest
1       2  2024-07-26 10:02:43.744  2024-07-26 10:12:51.666  1721959363744  1721959971666              0              0    warmup
2       3  2024-07-26 10:14:55.401  2024-07-26 10:20:05.269  1721960095401  1721960405269              1              1   running
3       4  2024-07-26 10:20:51.956  2024-07-26 10:25:56.202  1721960451956  1721960756202              1              1   running
4       5  2024-07-26 10:26:41.199  2024-07-26 10:31:44.879  1721960801199  1721961104879              2              2   running
5       6  2024-07-26 10:32:26.504  2024-07-26 10:37:31.309  1721961146504  1721961451309              2              2   running
6       7  2024-07-26 10:38:23.619  2024-07-26 10:43:27.862  1721961503619  1721961807862              2              3   running
7       9  2024-07-26 10:45:19.222  2024-07-26 10:50:24.031  1721961919222  1721962224031              3              3   running
8      10  2024-07-26 10:51:09.592  2024-07-26 10:56:14.403  1721962269592  1721962574403              4              3   running
9      11  2024-07-26 10:57:10.651  2024-07-26 11:02:17.715  1721962630651  1721962937715              5              5   running
10     12  2024-07-26 11:03:07.776  2024-07-26 11:08:14.278  1721962987776  1721963294278              6              6   running
11     13  2024-07-26 11:09:18.400  2024-07-26 11:14:23.216  1721963358400  1721963663216              8              8   running
12     14  2024-07-26 11:15:59.395  2024-07-26 11:21:05.337  1721963759395  1721964065337              9              9   running
13     15  2024-07-26 11:22:40.954  2024-07-26 11:27:43.526  1721964160954  1721964463526             10             10   running
14     16  2024-07-26 11:29:30.392  2024-07-26 11:32:47.789  1721964570392  1721964767789              2              2     stand
15     17  2024-07-26 11:33:26.041  2024-07-26 11:38:37.602  1721964806041  1721965117602              2              2  run_rest
    '''
    stage=[]
    
    df=ecg_df
    df.iloc[:, 0] = df.iloc[:, 0].apply(lambda x: int(str(x)[:13]))
    df['change'] = (df['stage'].ne(df['stage'].shift()) & (df['psychology_RPE']=='-') & (df['stage']!='-')).cumsum()
    df['ecg_time'] = pd.to_datetime(df.iloc[:, 0], unit='ms', utc=True).dt.tz_convert('Asia/Shanghai')
    df['ecg_time'] = df['ecg_time'].dt.strftime('%Y-%m-%d %H:%M:%S.%f').str[:-3]
   
    grouped = df.groupby('change')
    # print(df)
    for name, group in grouped:
        stagegroup=group[group['stage']!="-"]
        rpegroup=group[group['psychology_RPE']!="-"]
        # print('分段',group)

        # print(len(stagegroup),len(rpegroup))
        if len(stagegroup)>0 and len(rpegroup)>0:
            start_stamp=stagegroup.iloc[0,0]
            end_stamp=stagegroup.iloc[-1,0]
            start=stagegroup.iloc[0,6]
            end=stagegroup.iloc[-1,6]
            xlrpe=rpegroup.iloc[-1,3]
            slrpe=rpegroup.iloc[-1,4]
            # print(name,"开始为",start,'结束为',end)
            # print("rpe",xlrpe,'and',slrpe)
            stage.append([number,name,start,end,start_stamp,end_stamp,xlrpe,slrpe])
    df=pd.DataFrame(stage)


    df.columns=['number','stage','start_time','end_time','start_stamp','end_stamp','psychology_RPE','physiology_RPE']
    


    def get_stage_label(stage_value, num_stages):
        if stage_value == 1:
            return 'rest'
        elif stage_value == 2:
            return 'warmup'
        elif stage_value == int(num_stages)-1:
            return 'stand'
        elif stage_value == num_stages:
            return 'run_rest'
        else:
            return 'running'
    num_stages = df['stage'].iloc[-1]
    df['state']=df['stage'].apply(lambda x: get_stage_label(x, num_stages))

    return df



# 全部类型的数据读取
def df_get(deal_path,number):
    '''
    返回该deal中对应的df,输入例如1008-1-1
    :param deal_path: 文件存储路径
    :param person: 名称编号
    :param test: 实验编号
    :return:(ecg_df,rrdata_df,ppg_df,rri_df,singlework_df,singledetail_df) 返回对应的文件读取后的df（全部为字符串读取），可增加对应的类型
    '''
    person=number[0:4]

    path=deal_path+'\\'+person+'\\'+number

    ecg_df=pd.read_csv(path+'-ecg.csv',dtype=str)
    rrdata_df=pd.read_csv(path+'-rrdata.csv',dtype=str)
    ppg_df=pd.read_csv(path+'-ppg.csv',dtype=str)
    rri_df=pd.read_csv(path+'-rri.csv',dtype=str)
    singlework_df=pd.read_csv(path+'-singlework.csv',dtype=str)
    singledetail_df=pd.read_csv(path+'-singledetail.csv',dtype=str)


    return (ecg_df,rrdata_df,ppg_df,rri_df,singlework_df,singledetail_df)
#将number编号的数据转为csv，此过程中进行了合并
def data_to_csv(number,rootpath,typelist,dealpath):
    '''
    输入受试者编号，根目录，类型，输出根目录下该受试者该类型所有文件，并转为df，保存到dealpath中，
    :param number:受试者编号
    :param rootpath:根目录
    :param typelist:文件类型列表
    :param dealpath:输出目录
    :return:

    '''
    for type in typelist:
        filelist=numberfile_get(number,rootpath,type)
        df=fileTodf(filelist,type)
        
        #可在这里执行数据处理，也可等所有的数据存储到deal中后统一执行手工处理部分
        
        file_save(dealpath,df,number,type)


#保存成功后全部读取,或单独读取也可


#全部读取文件
def df_get(deal_path,number):
    '''
    返回该deal中对应的df,输入例如1008-1-1
    :param deal_path: 文件存储路径
    :param person: 名称编号
    :param test: 实验编号
    :return:(ecg_df,rrdata_df,ppg_df,rri_df,singlework_df,singledetail_df) 返回对应的文件读取后的df（全部为字符串读取），可增加对应的类型
    '''


    path=deal_path+'\\'+number[0:4]+'\\'+number

    ecg_df=pd.read_csv(path+'-ecg.csv',dtype=str)
    rrdata_df=pd.read_csv(path+'-rrdata.csv',dtype=str)
    ppg_df=pd.read_csv(path+'-ppg.csv',dtype=str)
    rri_df=pd.read_csv(path+'-rri.csv',dtype=str)
    singlework_df=pd.read_csv(path+'-singlework.csv',dtype=str)
    singledetail_df=pd.read_csv(path+'-singledetail.csv',dtype=str)


    return (ecg_df,rrdata_df,ppg_df,rri_df,singlework_df,singledetail_df)


#输入存储文件根目录，和df,建立下一级的目录，并将文件和type拼为一个文件名，保存文件
def file_save(deal_path,df,number,type):
    '''
    :param deal_path: 存储文件的根目录
    :param df: 待存储的df
    :param type: 文件类型
    :return:
    '''
    #创建文件夹
    path=deal_path+'\\'+number[0:4]
    if not os.path.exists(path):
        os.makedirs(path)
    filepath = path + '\\' + number +'-'+ type+'.csv'
    df.to_csv(filepath, index=False)
    # print('存储完毕')




#通过编号获取rootpath下该受试者的文件,只要存在该字符串的文件都返回
def numberfile_get(number,rootpath,type):
    """
    :param number: 受试者编号
    :param rootpath: 数据根目录
    :param type: 文件类型
    :return:该文件的路径列表
    """
    dirpath=os.path.join(rootpath, number[0:4])
    file_list=[]
    for root, dirs, files in os.walk(rootpath):
        for file in files:
            
            if type in file:
                if number in file:
                    

                    file_list.append(os.path.join(root, file))
    return file_list


#全局最大心率计算
def max_hr(df):
    '''
    # 输入为 df  ，
    # ，输入一个rrdata 的df，
    #  可用全局ecg的最大心率，也可用于每个阶段的最大心率，还可用于singledeail阶段的最大心率
    :param df:  rrdata_df或  rrdata的一部分
    :param hr_col:  hr所在的列名
    :return: 最大心率  str
    '''
    data = df.iloc[:, 1].astype('int64').tolist()

    # 滑动窗口参数
    window_size = 10
    step_size = 1

    # 存储滑动窗口的平均值
    rolling_means = []

    # 计算滑动窗口的平均值
    for i in range(0, len(data) - window_size + 1, step_size):
        window = data[i:i + window_size]
        window_mean = sum(window) / window_size
        rolling_means.append(window_mean)

    # 找到最大的平均值
    max_mean = max(rolling_means) if rolling_means else None

    # 输出结果
    # print("滑动窗口的平均值列表：")
    # print(rolling_means)
    print("心率最大的平均值：")
    print(max_mean)
    return max_mean







#得到每个阶段的hr
def get_stage_hr(rrdata_df,singledetail_df,start_time,end_time,step):

    '''
       同理
       :param rrdata_df:
       :param singledetail_df:
       :param start_time:
       :param end_time:
       :return:
       '''
    #     从给的stagedf中获取，获取每个阶段的开始和结束时间
    rrdata_df['timestamp'] = rrdata_df['timestamp'].astype('int64')
    singledetail_df['timestamp'] = singledetail_df['timestamp'].astype('int64')

    # print(singledetail_df)
    #   循环找到每个阶段的df
    step = step * 1000
    stage_rrdata = rrdata_df[(rrdata_df['timestamp'] > start_time+step) & (rrdata_df['timestamp'] < end_time-step)]
    stage_singledetail = singledetail_df[
        (singledetail_df['timestamp'] > start_time+step) & (singledetail_df['timestamp'] < end_time-step)]



    stage_rrdata['combined'] = stage_rrdata.apply(lambda row: [row['timestamp'], row['HR']], axis=1)
    polar_hr =[[int(item[0]), int(item[1])] for item in stage_rrdata['combined'].tolist()]
    if len(stage_singledetail) >= 2:
        stage_singledetail['combined'] = stage_singledetail.apply(lambda row: [row['timestamp'], row['心率']], axis=1)

    huawei_hr= [[int(item[0]), int(item[1])] for item in stage_singledetail['combined'].tolist()]
    # print(polar_hr)
    # print(huawei_hr)

    return polar_hr,huawei_hr


#得到每个阶段的RR
def get_stage_rr(rrdata_df,rri_df,start_time,end_time,step):
    '''
    #返回每个阶段的rrdata与rri的序列，step  前后时间间隔step 单位秒
    :param rrdata_df:
    :param rri_df:
    :param start_time: 开始时间
    :param end_time: 结束时间
    :param step: 前后截取
    :return:
    example:两个列表，带时间戳
    1:[[1718604976460, 706], [1718604977166, 733], [1718604977583, 703], [1718604978705, 747], [1718604979266, 768],]
    [[1718604976861, 1214], [1718604977827, 966], [1718604978523, 696], [1718604979184, 661], [1718604979929, 745],]
    '''
    #     从给的stagedf中获取，获取每个阶段的开始和结束时间
    rrdata_df['timestamp'] = rrdata_df['timestamp'].astype('int64')
    rri_df['timestamp'] = rri_df['timestamp'].astype('int64')

    #   循环找到每个阶段的df
    step = step * 1000
    stage_rrdata = rrdata_df[(rrdata_df['timestamp'] > start_time + step) & (rrdata_df['timestamp'] < end_time - step)]
    stage_rri = rri_df[(rri_df['timestamp'] > start_time+ step) & (rri_df['timestamp'] < end_time - step) & (rri_df['sqi'] == '100')]


    stage_rrdata['combined'] = stage_rrdata.apply(lambda row: [row['timestamp'], row['rr']], axis=1)
    stage_rrdata2=stage_rrdata['combined'].tolist()

    if len(stage_rri)>=2:
        stage_rri['combined']=stage_rri.apply(lambda row: [row['timestamp'], row['value']], axis=1)
        rri_result =[[int(item[0]), int(item[1])] for item in stage_rri['combined'].tolist()]
    else:
        rri_result=[]


    rr_result = []

    # 处理数据
    for item in stage_rrdata2:
        # 使用eval将字符串转换为实际的列表对象
        list_obj = eval(item[1])
        # 使用filter去除空值，并转换为整数
        cleaned_list = list(map(int, filter(None, [x.strip() for x in list_obj])))

        # 对每个整数值生成一个新的子列表，并添加到结果列表中
        for i,value in enumerate(cleaned_list):
            if i == 0:
                rr_result.append([int(item[0]), value])
            else:
                previous = cleaned_list[i - 1]

                rr_result.append([int(item[0])+previous, value])

    # print('rrresult',rr_result)
    # print('rriresult',rri_result)


    # stage_rri2 = [int(item) for item in stage_rri['value'].tolist() if item != '0']

    return rr_result,rri_result